package com.mingqijia.gassafety.webserver.service.cmp;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.BetweenFormatter;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.gap.basic.exception.BizException;
import com.github.pagehelper.util.StringUtil;
import com.mingqijia.gassafety.db.entity.*;
import com.mingqijia.gassafety.db.influxdb.config.InfluxDBConfiguration;
import com.mingqijia.gassafety.db.influxdb.config.InfluxDBConnect;
import com.mingqijia.gassafety.db.mapper.*;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.constant.EquipmentType;
import com.mingqijia.gassafety.shared.constant.EquipmentTypeConst;
import com.mingqijia.gassafety.shared.utils.DateFormatUtil;
import com.mingqijia.gassafety.shared.utils.message.SendMessageService;
import com.mingqijia.gassafety.shared.vcc.VccAuthoritiesProvider;
import com.mingqijia.gassafety.webserver.dto.NotifyDTO;
import com.mingqijia.gassafety.webserver.dto.ReportNotifyDTO;
import com.mingqijia.gassafety.webserver.dto.ReportNotifyOfflineDTO;
import com.mingqijia.gassafety.webserver.request.BrowserNotifyItemRequest;
import com.mingqijia.gassafety.webserver.request.BrowserNotifyReason;
import com.mingqijia.gassafety.webserver.request.cmp.notify.DataReportDataRequest;
import com.mingqijia.gassafety.webserver.request.cmp.notify.DataReportRequest;
import com.mingqijia.gassafety.webserver.service.*;
import com.mingqijia.gassafety.webserver.service.impl.CompanyServiceImpl;
import com.mingqijia.gassafety.webserver.service.impl.HistoryAlarmServiceImpl;
import com.mingqijia.gassafety.webserver.service.impl.WarningDataServiceImpl;
import com.mingqijia.gassafety.webserver.service.zj.ZjWifiService;
import com.mingqijia.gassafety.webserver.utils.ApplicationContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.mingqijia.gassafety.webserver.constant.DeviceConstant.*;

/**
 * CMP平台回调抽象类
 *
 * @author zhufeng
 * @since 2022/8/1
 */
@Slf4j
public abstract class AbstractCmpDataNotifyService implements CmpDataNotifyService {
    public static final DeviceState DEVICE_STATE = new DeviceState();
    @Value("${wx.server.externalUrl}")
    private String gasWechatUrl;
    public static final String format = "yyyy-MM-dd HH:mm:ss";
    @Value("${console.server.externalUrl}")
    private String consoleUrl;

    @Value("${zj.wifi.valve.code_ignore:}")
    private String zjWifiValveCodeIgnore;

    private final static String split_m = ":";
    public static final String split = ";";

    private CompanyServiceImpl companyService;

    private BusinessNoticeMapper businessNoticeMapper;

    public static final String CM_SERVICE_HOT_LINE = "cm_service_hot_line";

    private RecordDetectorService detectorService;

    private SendMessageService sendMessageService;

    private BusinessNoticeMapper noticeMapper;

    private ContactsMapper contactsMapper;

    private WarnStrategyMapper warnStrategyMapper;

    private VccAuthoritiesProvider provider;

    private RecordControllerService recordControllerService;

    private DtuMapper dtuMapper;

    private EquipmentService equipmentService;

    private DeviceStateMapper deviceStateMapper;

    private RecordDtuService recordDtuService;

    private ResetlogService resetlogService;

    private HistoryAlarmMapper historyAlarmMapper;

    private HistoryBrokenMapper historyBrokenMapper;

    private BrowserNotifyService browserNotifyService;

    private DepartmentService departmentService;

    private WarningDataServiceImpl warningDataService;

    private ZjWifiService zjWifiService;

    private RecordReceiverValveService recordReceiverValveService;

    private HistoryAlarmServiceImpl historyAlarmService;

    private WorkOrderHistoryMapper workOrderHistoryMapper;
    private GssOfflineMapper gssOfflineMapper;

    @Autowired
    private AppealLogService appealLogService;
    
    @Autowired
    ConsumerLocationService consumerLocationService;

    @Autowired
    InfluxDBConfiguration influxDBConfiguration;

    @Autowired
    SmartKitchenService smartKitchenService;

    @Autowired
    DtuAepMapper dtuAepMapper;
    @Resource
    WorkOrderHandleService workOrderHandleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public NotifyDTO saveReportData(DataReportRequest dataReportRequest) throws BizException {
        if (!CollectionUtils.isEmpty(dataReportRequest.getData())) {
            for (DataReportDataRequest datum : dataReportRequest.getData()) {
                //气体是甲烷并且浓度超过100时，数据丢弃
                if ("T".equals(datum.getGasType()) && (datum.getConcentration()!=null&&datum.getConcentration() > 100)) {
                    log.info(dataReportRequest.getDeviceCode() + ":气体是甲烷并且浓度超过100,错误数据丢弃");
                    throw new BizException(dataReportRequest.getDeviceCode() + ":气体是甲烷并且浓度超过100,错误数据丢弃");
                }
            }
        }
        //上报数据落库
        NotifyDTO notifyDTO = saveData(dataReportRequest);

        log.info("saveReportData->notifyDTO:{}",JSONObject.toJSONString(notifyDTO));
        return notifyDTO;
    }


    @Override
    public void notifyState(NotifyDTO notifyDTO) {
        //设备开关机推送
        if (notifyDTO.getOfflineDTO() != null) offlineNotify(notifyDTO.getOfflineDTO());
        //故障,报警消息推送
        if (CollectionUtil.isNotEmpty(notifyDTO.getReportNotifyDTOList())) {
            List<String> imeiList = notifyDTO.getReportNotifyDTOList().stream().map(
                    item->item.getDtu().getIMEI()
            ).collect(Collectors.toList());
            List<Dtu> dtuList = equipmentService.queryDeviceByImei(imeiList, notifyDTO.getSpId());
            Map<String,Dtu> dtuMap = dtuList.stream().collect(Collectors.toMap(Dtu::getIMEI,item->item));
            for (ReportNotifyDTO dto : notifyDTO.getReportNotifyDTOList()) {
                checkDeviceState(dto, dtuMap);
            }
        }
    }

    /**
     * 上报数据落库
     *
     * @param dataReportRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    protected NotifyDTO saveData(DataReportRequest dataReportRequest) {
        //需要推送的数据
        NotifyDTO dto = new NotifyDTO();
        List<ReportNotifyDTO> notifyDTOS = new ArrayList<>();
        //未绑定客户的设备不存数据
        List<Dtu> dtuList = getDtuByDeviceCode(dataReportRequest.getDeviceCode());
        if (dtuList == null || dtuList.isEmpty()) {
            log.error("getDtuByDeviceCode return null, deviceCode:{}未绑定客户", dataReportRequest.getDeviceCode());
            throw new BizException(1009, "deviceCode:" + dataReportRequest.getDeviceCode() + ",未绑定客户!");
        }

        if (deviceStateMapper == null) {
            deviceStateMapper = ApplicationContextUtils.getBean(DeviceStateMapper.class);
        }
        Dtu dtu = dtuList.get(0);
        //更新过期时间
        if (Constants.ZJ_EQUIPMENT_FROM == dtu.getEquipmentFrom()) {
            Integer workingDays = dataReportRequest.getWorkingDays();
            updateExpirationTime(dtu, workingDays);
        }

        //控制器部分 数据预处理
        DeviceState prepareDeviceState = prepareDeviceState(dataReportRequest, dtu);
        RecordController recordController = prepareRecordController(dataReportRequest, dtu);
        log.info("saveReportData of prepareDeviceState:{} ", JSONObject.toJSONString(prepareDeviceState));
        log.info("saveReportData of recordController:{} ", JSONObject.toJSONString(recordController));

        //当设备掉电,设备及关联探测器离线; 开关机时视data为无效数据, 返回true
        ReportNotifyOfflineDTO offlineDTO = updateDeviceOffline(dataReportRequest, recordController, prepareDeviceState, dtu);
        //如果 change = true , 则只落数据,不修改设备状态
        if (offlineDTO != null && offlineDTO.getChange()) {
            log.info("设备:{} 进行开关机上报.", dtu.getId());
            //过滤校验
            if (checkRecord(recordController, dataReportRequest, dtu)) {
                log.info("过滤校验通过");
                RecordController controller = saveRecordController(recordController);
                saveReportDtu(prepareRecordDtu(dataReportRequest, dtu, controller.getId()));
                saveDetectorList(dataReportRequest, dtu, controller.getId());
                //save 接收器
                if (dtu.getEquipmentFrom().equals(Constants.ZJ_EQUIPMENT_FROM)) {
                    saveReceiverValve(dataReportRequest, dtu, controller.getId(), null, offlineDTO);
                }
                dto.setOfflineDTO(offlineDTO);
            }
        } else {
            // 本次非开关机推送，设备之前是离线状态，新增一条开机记录（用于给设备周期性离线判定的关机但其实未关机，可以继续上报数据的开机逻辑）
            powerRecord(dtu);
            //只要有数据上报,更新(控制器部分)设备状态
            ReportNotifyDTO notifyDTO = updateDeviceState(prepareDeviceState, dataReportRequest, dtu);
            //过滤校验
            if (checkRecord(recordController, dataReportRequest, dtu)) {
                log.info("过滤校验通过");
                RecordController controller = saveRecordController(recordController);
                //更新record_dtu
                saveReportDtu(prepareRecordDtu(dataReportRequest, dtu, controller.getId()));
                // 根据data(探测器)数据, 进行更新;注意家报和一体
                List<ReportNotifyDTO> detectorNotifyDTOList = saveDetectorList(dataReportRequest, dtu, controller.getId());
                //save 接收器
                if (dtu.getEquipmentFrom().equals(Constants.ZJ_EQUIPMENT_FROM)) {
                    saveReceiverValve(dataReportRequest, dtu, controller.getId(), notifyDTO, null);
                }
                notifyDTOS.add(notifyDTO);
                notifyDTOS.addAll(detectorNotifyDTOList);
                dto.setReportNotifyDTOList(notifyDTOS);
            }
        }

        //更新客户的设备数量
        consumerLocationService.updateConsumerLocationDeviceNumByDtu(dtu);

        //仅1.0设备未激活的更新激活时间及设备到期时间
        activeV1Device(dtu,recordController);

        dto.setSpId(dtu.getSpId());
        dto.setConsumerId(dtu.getConsumerId());
        dto.setImei(dtu.getIMEI());

        return dto;
    }

    /**
     * 激活本安V1.0设备
     */
    private void activeV1Device(Dtu dtu,RecordController recordController){
        try {
            if ( "v1.0".equals(dtu.getProtocolVersion()) && ObjectUtils.isNotEmpty(recordController.getRecordAt()) ) {
                Date recordAt = recordController.getRecordAt();
                String formatDate = DateUtil.format(recordAt, "yyyy-MM-dd HH:mm:ss");
                DateTime parse = DateUtil.parse(formatDate);
                List<DtuAep> dtuAepList = dtuAepMapper.selectCmpListByImei(dtu.getIMEI(), dtu.getSpId());
                for (DtuAep dtuAep:dtuAepList) {
                    if (StringUtils.isEmpty(dtuAep.getActivateTime())) {
                        dtuAep.setActivateStatus(1);
                        dtuAep.setActivateTime(formatDate);
                        log.info("activeV1Device-更新：{}的激活时间:{}",
                                dtu.getIMEI(), JSONObject.toJSONString(dtuAep));
                        dtuAepMapper.updateById(dtuAep);

                        dtu.setExpirationTime(DateUtil
                                .offsetMonth(parse, ObjectUtils.isEmpty(dtu.getValidity()) ? 0 : dtu.getValidity() * 12).toString(format));
                        log.info("activeV1Device-更新设备过期时间：{}", JSONObject.toJSONString(dtu));
                        dtuMapper.updateById(dtu);
                    }
                }
            }
        }catch (Exception e){
            log.error("激活设备失败",e);
        }
    }

    private void updateExpirationTime(Dtu dtu, Integer workingDays) {
        log.info("updateExpirationTime-param:{}", workingDays, dtu.getIMEI());
        //跟曾凡归确认上报数据中的workdays只有正整数时需要处理
        if (workingDays == null || workingDays < 1) {
            return;
        }
        try {
            String registerTime = dtu.getRegisterTime();
            if (!StringUtils.isNotBlank(registerTime)) return;
            List<String> days = DateFormatUtil.getDays(registerTime,
                    DateUtil.format(new Date(), DateFormatUtil.YYMMDDHHmmss),
                    DateFormatUtil.YYMMDDHHmmss, 1, new ArrayList<>());
            if (workingDays != null && workingDays != 0) {
                dtu.setExpirationTime(DateUtil.offsetDay(DateUtil.parse(registerTime),
                        5 * 365 + (days.size() - workingDays)).toString(format));
                log.info("update-expirationTime dtu:{}", JSONObject.toJSONString(dtu));
                UpdateWrapper<Dtu> wrapper = new UpdateWrapper<>();
                wrapper.lambda().or().eq(Dtu::getIsDeleted, 0)
                        .eq(Dtu::getIMEI, dtu.getIMEI());
                dtuMapper.update(dtu, wrapper);
            }

        } catch (Exception e) {
            log.error("update-expirationTime error:{}", e);
        }
    }


    /**
     * 不同接口,设置设备状态
     *
     * @param dataReportRequest
     * @param dtu
     * @return
     */
    protected abstract DeviceState prepareDeviceState(DataReportRequest dataReportRequest, Dtu dtu);

    /**
     * 根据 探测器信息更新设备状态
     *
     * @param t
     * @param newDtu
     * @return
     */
    protected abstract DeviceState updateDeviceStateByDetector(DataReportDataRequest t, Dtu newDtu, Integer controllerStatus);

    protected abstract RecordController prepareRecordController(DataReportRequest dataReportRequest, Dtu dtu);

    protected abstract RecordDetector prepareRecordDetector(DataReportDataRequest t, Dtu newDtu);

    protected RecordDtu prepareRecordDtu(DataReportRequest dataReportRequest, Dtu dtu, Long controllerId) {
        RecordDtu recordDtu = new RecordDtu();
        recordDtu.setRecordId(controllerId);
        recordDtu.setDeviceId(dtu.getId());
        recordDtu.setConsumerId(dtu.getConsumerId());
        recordDtu.setRecordType(dataReportRequest.getRecordType());
        recordDtu.setRecordAt(dataReportRequest.getReportDate());
        recordDtu.setSpId(dtu.getSpId());
        if (dataReportRequest.getSignal() != null) {
            recordDtu.setSingal(dataReportRequest.getSignal());
        }
        return recordDtu;
    }


    /**
     * 消息通知入参预处理
     *
     * @param prepareDeviceState
     * @param dtu
     * @param reason
     * @return
     */
    protected List<BrowserNotifyItemRequest> prepareBrowserNotifyItem(DeviceState prepareDeviceState, Dtu dtu, BrowserNotifyReason reason) {
        //入参dtu可能是 探测器的
        ArrayList<BrowserNotifyItemRequest> list = new ArrayList<>();
        BrowserNotifyItemRequest itemRequest = new BrowserNotifyItemRequest();
        String sub = StringUtils.substringAfter(dtu.getIMEI(), "-");
        String dtuId = StringUtils.substringBefore(dtu.getIMEI(), "-");
        itemRequest.setReason(reason); //枚举
        if (prepareDeviceState.getConcentration() != null) {
            itemRequest.setXlel(prepareDeviceState.getConcentration());
        }
        itemRequest.setEquipmentType(dtu.getEquipmentType());
        itemRequest.setSubIdentifier(sub);
        itemRequest.setDtuId(dtuId);
        itemRequest.setLogTime(new Date());
        itemRequest.setEquipmentFrom(dtu.getEquipmentFrom());
        String factoryName = equipmentService.getEquipmentManufacturerName(dtu.getEquipmentManufacturer(),dtu.getSpId());
        itemRequest.setFactoryName(factoryName);
        list.add(itemRequest);
        return list;
    }


    /**
     * 各项数据上报入库
     */
    protected RecordController saveRecordController(RecordController prepareRecordController) {

        if (recordControllerService == null) {
            recordControllerService = ApplicationContextUtils.getBean(RecordControllerService.class);
        }
        recordControllerService.getBaseMapper().insert(prepareRecordController);
        return prepareRecordController;
    }

    private void saveRecordDetector(RecordDetector detector) {
        if (detectorService == null) {
            detectorService = ApplicationContextUtils.getBean(RecordDetectorService.class);
        }
        detectorService.save(detector);
    }

    protected void saveReportDtu(RecordDtu prepareRecordDtu) {
        if (recordDtuService == null) {
            recordDtuService = ApplicationContextUtils.getBean(RecordDtuService.class);
        }

        if (prepareRecordDtu != null) {
            recordDtuService.save(prepareRecordDtu);
        }
    }

    protected List<ReportNotifyDTO> saveDetectorList(DataReportRequest request, Dtu dtu, Long controllerId) {
        if (equipmentService == null) {
            equipmentService = ApplicationContextUtils.getBean(EquipmentService.class);
        }

        List<ReportNotifyDTO> notifyDTOS = new ArrayList<>();

        //获取设备及其探头数据
        Map<String,Dtu> dtuMap = new HashMap<>();
        if (StringUtils.isNotEmpty(dtu.getIMEI())){
            List<Dtu> dtuList = dtuMapper.selectBatchByImeiDelete(dtu.getIMEI(),"");
            if (null!=dtuList && !dtuList.isEmpty()) {
                dtuMap = dtuList.stream().collect(Collectors.toMap(Dtu::getIMEI, item -> item));
            }
        }
        log.info("saveDetectorList dtuMap:{}",JSONObject.toJSONString(dtuMap));

        //遍历探头数据
        for (DataReportDataRequest t : request.getData()) {
            t.setRecordAt(request.getReportDate());
            t.setRecordId(controllerId);
            t.setSpId(dtu.getSpId());
            //判断设备类型
            if (EquipmentType.GAS_ALARM_CONTROLLER.getCode().equals(dtu.getEquipmentType())) {
                //对于(控制-探测组合)设备,返回探测器数据(已有consumerId
                // v1.0探测器,保留回路信息, 例:sub=21时, 需拆分为2-1;  newDtu为已处理结果
                Dtu newDtu = equipmentService.deviceInfo(dtuMap, dtu.getIMEI(), String.valueOf(t.getSno()));
                if (newDtu == null) {
                    log.error("equipmentService.deviceInfo return null");
                }
                if (newDtu != null) {
                    //更新探头状态
                    saveRecordDetector(prepareRecordDetector(t, newDtu));
                    //非开关机上报内容,进行更新&推送
                    if (!(WORK_STATUS_1.equals(request.getWorkStatus()) || WORK_STATUS_2.equals(request.getWorkStatus())
                            || WORK_STATUS_4.equals(request.getWorkStatus()))) {
                        //修改探测器deviceState
                        DeviceState preDeviceState = updateDeviceStateByDetector(t, newDtu, null);
                        log.info("EquipmentType = GAS_ALARM_CONTROLLER , preDeviceState:{} ", preDeviceState);
                        //更新探头设备状态
                        ReportNotifyDTO notifyDTO = updateDeviceState(preDeviceState, request, newDtu);
                        notifyDTOS.add(notifyDTO);
                    }
                }
            } else if (EquipmentType.POINT_TYPE_GAS_DETECTOR.getCode().equals(dtu.getEquipmentType())) {
                throw new BizException("deviceCode:" + request.getDeviceCode() + "对应设备类型为探测器,不应该为上报数据主体");
            } else {
                //更新探头状态
                saveRecordDetector(prepareRecordDetector(t, dtu));
                //非开关机上报内容,进行更新&推送
                if (!(WORK_STATUS_1.equals(request.getWorkStatus()) || WORK_STATUS_2.equals(request.getWorkStatus())
                        || WORK_STATUS_4.equals(request.getWorkStatus()))) {
                    if( !EquipmentType.HOME_GAS_DETECTOR.getCode().equals(dtu.getEquipmentType()) ){
                        //更新总设备状态
                        DeviceState preDeviceState = updateDeviceStateByDetector(t, dtu, request.getControllerStatus());
                        ReportNotifyDTO notifyDTO = updateDeviceState(preDeviceState, request, dtu);
                        log.info("EquipmentType != GAS_ALARM_CONTROLLER , preDeviceState:{} ", preDeviceState);
                        notifyDTOS.add(notifyDTO);
                    }else if( !("v1.0".equals(dtu.getProtocolVersion()) && request.getData().size()==2 && 
                            notifyDTOS.size()>0 && null!=t.getAlarmType() && t.getAlarmType().equals(3)) ) { //1.0 且 设备类型是家用燃气报警器 且上报2个探头数据
                        //更新总设备状态
                        DeviceState preDeviceState = updateDeviceStateByDetector(t, dtu, request.getControllerStatus());
                        ReportNotifyDTO notifyDTO = updateDeviceState(preDeviceState, request, dtu);
                        log.info("EquipmentType != GAS_ALARM_CONTROLLER , preDeviceState:{} ", preDeviceState);
                        notifyDTOS.add(notifyDTO);
                    }
                }
            }
        }

        log.info("saveDetectorList() -- 更新设备状态 -- notifyDTOS: {}", JSONObject.toJSONString(notifyDTOS));
        return notifyDTOS;
    }


    /**
     * 过滤冗余数据的check
     */
    protected boolean checkRecord(RecordController prepareRecordController, DataReportRequest request, Dtu dtu) {

        if (recordControllerService == null) {
            recordControllerService = ApplicationContextUtils.getBean(RecordControllerService.class);
        }
        if (detectorService == null) {
            detectorService = ApplicationContextUtils.getBean(RecordDetectorService.class);
        }
        if (recordReceiverValveService == null) {
            recordReceiverValveService = ApplicationContextUtils.getBean(RecordReceiverValveService.class);
        }
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 格式化日期为字符串，例如："yyyy-MM-dd"
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String formattedDate = today.format(formatter);

        QueryWrapper<RecordController> controllerQueryWrapper = new QueryWrapper<>();
        controllerQueryWrapper.lambda().gt(RecordController::getCreatedAt, formattedDate)
                .eq(RecordController::getDeviceId, prepareRecordController.getDeviceId())
                .eq(RecordController::getSpId, prepareRecordController.getSpId())
                .eq(RecordController::getIsDeleted, 0)
                .orderByDesc(RecordController::getCreatedAt).last("limit 1");
        RecordController controller = recordControllerService.getBaseMapper().selectOne(controllerQueryWrapper);
        //控制器记录表校验
        //一天当中还没有记录，则需要记录
        if (controller == null) {
            return true;
        }
        log.info("checkRecord controller old:" + controller);
        log.info("prepareRecordController :" + prepareRecordController);
        //一天当中控制器状态、工作运行状态、供电类型、探测器数量发生变化，则需要记录
        if (!Objects.equals(controller.getControllerStatus(), prepareRecordController.getControllerStatus()) ||
                !Objects.equals(controller.getWorkStatus(), prepareRecordController.getWorkStatus()) ||
                !Objects.equals(controller.getPowerModel(), prepareRecordController.getPowerModel()) ||
                !Objects.equals(controller.getDetectorCount(), prepareRecordController.getDetectorCount())) {
            log.info("controller OK");
            return true;
        }

        //获取设备最后上报的探头数据
        Map<String,RecordDetector> recordDetectorMap = getDeviceLastReportDetector(dtu,
                formattedDate,
                prepareRecordController.getSpId(),
                controller.getId()
        );

        //探测器记录表校验
        for (DataReportDataRequest t : request.getData()) {
            //判断设备类型
            if (EquipmentType.GAS_ALARM_CONTROLLER.getCode().equals(dtu.getEquipmentType())) {
                String imei = dtu.getIMEI();
                String point = String.valueOf(t.getSno());
                if ("v2.0".equals(dtu.getProtocolVersion())) {
                    imei = dtu.getIMEI() + Constants.EQUIPMENTI_CONSTANT + point;
                } else if ("v1.0".equals(dtu.getProtocolVersion())) {
                    String loop = "";
                    if (point.length() < 2) {
                        loop = "1";
                    } else {
                        loop = point.substring(0, 1);
                    }
                    imei = imei + "-" + loop + "-" + point.substring(1, point.length());
                }
                log.info("imei:" + imei);
                RecordDetector recordDetector = recordDetectorMap.getOrDefault(imei,null);
                if (recordDetector == null) return true;
                log.info("checkRecord recordDetector old:" + recordDetector);
                log.info("DataReportDataRequest :" + t);
                //一天当中探头记录中，气体类型（甲烷、CO、丙烷、氢气），状态（正常、寿命到期、探测器故障、传感器故障等），
                // 报警类型（报警恢复、低限报警、高限报警、变化监测、报警），浓度值、湿度温度发生变化，则需要记录
                if (!Objects.equals(recordDetector.getGasType(), t.getGasType()) ||
                        !Objects.equals(recordDetector.getDetectorStatus(), t.getDetectorStatus()) ||
                        !Objects.equals(recordDetector.getAlertType(), t.getAlarmType()) ||
                        !Objects.equals(recordDetector.getConcentration(), t.getConcentration()) ||
                        !Objects.equals(recordDetector.getHumidity(), t.getHumidity()) ||
                        !Objects.equals(recordDetector.getTemperature(), t.getTemperature())) {
                    return true;
                }
            } else if (EquipmentType.POINT_TYPE_GAS_DETECTOR.getCode().equals(dtu.getEquipmentType())) {
                return false;
            } else {
                String mpKey = dtu.getId()+"_"+(StringUtils.isEmpty(t.getGasType())?"":t.getGasType());
                log.info("checkRecord recordDetector key:" + mpKey);
                RecordDetector recordDetector = recordDetectorMap.getOrDefault(mpKey,null);
                if (recordDetector == null) return true;
                log.info("checkRecord recordDetector old:" + recordDetector);
                log.info("DataReportDataRequest :" + t);
                //一天当中探头记录中，气体类型（甲烷、CO、丙烷、氢气），状态（正常、寿命到期、探测器故障、传感器故障等），
                // 报警类型（报警恢复、低限报警、高限报警、变化监测、报警），浓度值、湿度温度发生变化，则需要记录
                if (!Objects.equals(recordDetector.getGasType(), t.getGasType()) ||
                        !Objects.equals(recordDetector.getDetectorStatus(), t.getDetectorStatus()) ||
                        !Objects.equals(recordDetector.getAlertType(), t.getAlarmType()) ||
                        !Objects.equals(recordDetector.getConcentration(), t.getConcentration()) ||
                        !Objects.equals(recordDetector.getHumidity(), t.getHumidity()) ||
                        !Objects.equals(recordDetector.getTemperature(), t.getTemperature())) {
                    return true;
                }
            }
        }
        //电磁阀的校验
        if (dtu.getEquipmentFrom().equals(Constants.ZJ_EQUIPMENT_FROM)) {
            QueryWrapper<RecordReceiverValve> receiverValveQueryWrapper = new QueryWrapper<>();
            receiverValveQueryWrapper.lambda().gt(RecordReceiverValve::getCreatedAt, formattedDate)
                    .eq(RecordReceiverValve::getDeviceId, dtu.getId())
                    .eq(RecordReceiverValve::getSpId, prepareRecordController.getSpId())
                    .eq(RecordReceiverValve::getIsDeleted, 0)
                    .eq(RecordReceiverValve::getRecordId, controller.getId())
                    .orderByDesc(RecordReceiverValve::getCreatedAt).last("limit 1");
            RecordReceiverValve valve = recordReceiverValveService.getBaseMapper().selectOne(receiverValveQueryWrapper);
            if (valve == null) return true;
            log.info("checkRecord recordReceiverValve old:" + valve);
            log.info("DataReportRequest :" + request);
            //一天当中电磁阀记录中，电磁阀id、接收器状态、电磁阀工作状态、阀门状态、故障状态发生变化，则需要记录
            if (VALVE_CONNECTION_0.equals(request.getValveConnection())) {
                if (!valve.getReceiverStatus().equals(RECEIVER_STATUS_OFFLINE)) {
                    return true;
                }
            } else {
                if (!valve.getReceiverStatus().equals(RECEIVER_STATUS_NORMAL)) {
                    return true;
                }
                if (request.getValveConnection() > 1) {
                    if (!valve.getValveId().equals(String.valueOf(request.getValveConnection()))) {
                        return true;
                    }
                }
            }
            if (!Objects.equals(valve.getValveWorkStatus(), request.getValveWorkStatus()) ||
                    !Objects.equals(valve.getValveStatus(), request.getValveStatus()) ||
                    !Objects.equals(valve.getBrokenStatus(), request.getValveStatusDesc())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取设备最后上报的探测器数据
     * @param dtu
     * @param formattedDate
     * @param spId
     * @param recordId
     * @return
     */
    private Map<String,RecordDetector> getDeviceLastReportDetector(Dtu dtu,String formattedDate,String spId, Long recordId){
        Map<String,RecordDetector> recordDetectorMap = new HashMap<>();
        try {
            QueryWrapper<RecordDetector> detectorQueryWrapper = new QueryWrapper<>();
            if (EquipmentType.GAS_ALARM_CONTROLLER.getCode().equals(dtu.getEquipmentType())) {
                detectorQueryWrapper.lambda().gt(RecordDetector::getCreatedAt, formattedDate)
                        .eq(RecordDetector::getSpId, spId)
                        .eq(RecordDetector::getIsDeleted, 0)
                        .eq(RecordDetector::getRecordId, recordId)
                        .orderByAsc(RecordDetector::getCreatedAt);
                List<RecordDetector> recordDetectors = detectorService.getBaseMapper().selectList(detectorQueryWrapper);
                if (null != recordDetectors && !recordDetectors.isEmpty()) {
                    recordDetectorMap = recordDetectors.stream().collect(Collectors.toMap(RecordDetector::getDeviceId, item -> item));
                }
            } else if (!EquipmentType.POINT_TYPE_GAS_DETECTOR.getCode().equals(dtu.getEquipmentType())) {
                detectorQueryWrapper.lambda().gt(RecordDetector::getCreatedAt, formattedDate)
                        .eq(RecordDetector::getDeviceId, dtu.getId())
                        .eq(RecordDetector::getSpId, spId)
                        .eq(RecordDetector::getIsDeleted, 0)
                        .eq(RecordDetector::getRecordId, recordId)
                        .orderByAsc(RecordDetector::getCreatedAt);
                List<RecordDetector> recordDetectors = detectorService.getBaseMapper().selectList(detectorQueryWrapper);
                if (null != recordDetectors && !recordDetectors.isEmpty()) {
                    String tmpKey = "";
                    for (RecordDetector recordDetector : recordDetectors) {
                        tmpKey = recordDetector.getDeviceId() + "_" + (StringUtils.isEmpty(recordDetector.getGasType()) ? "" : recordDetector.getGasType());
                        recordDetectorMap.put(tmpKey, recordDetector);
                    }
                }
            }
            log.info("checkRecord LastReportDetector:{}",JSONObject.toJSONString(recordDetectorMap));
        }catch (Exception e){
            log.error("getDeviceLastReportDetector error:",e);
        }
        return recordDetectorMap;
    }

    /**
     * 接收器和电磁阀上报
     *
     * @param request
     * @param dtu
     * @param controllerId
     */
    protected abstract void saveReceiverValve(DataReportRequest request, Dtu dtu, Long controllerId, ReportNotifyDTO notifyDTO, ReportNotifyOfflineDTO offlineDTO);

    /**
     * 更新 报警器实时状态
     *
     * @param prepareDeviceState
     * @param request
     * @param dtu
     */
    protected ReportNotifyDTO updateDeviceState(DeviceState prepareDeviceState, DataReportRequest request, Dtu dtu) {
        ReportNotifyDTO dto = new ReportNotifyDTO();

        DeviceState deviceState = getStateByDeviceId(prepareDeviceState.getDeviceId(), prepareDeviceState.getSpId());
        if (deviceState == null) {
            //当设备第一次上报,  预设设备状态正常
            log.info("设备 id:{} 为第一次上报,预设此前状态为正常", dtu.getId());
            DeviceState deviceStateNew = new DeviceState();
            deviceStateNew.setDeviceStatus(DEVICE_STATUS_1);
            deviceStateNew.setDeviceId(prepareDeviceState.getDeviceId());
            dto.setDeviceState(deviceStateNew);
            dto.setPrepareDeviceState(prepareDeviceState);
            dto.setRequest(request);
            dto.setDtu(dtu);
            prepareDeviceState.setLastReportTime(new Date());
            deviceStateMapper.insert(prepareDeviceState);
        } else {
            prepareDeviceState.setId(deviceState.getId());
            if (request.getWorkingDays() != null) {
                prepareDeviceState.setWorkingDays(request.getWorkingDays());
            }
            dto.setDeviceState(deviceState);
            dto.setPrepareDeviceState(prepareDeviceState);
            dto.setRequest(request);
            dto.setDtu(dtu);
            prepareDeviceState.setLastReportTime(new Date());
            deviceStateMapper.updateById(prepareDeviceState);
            //消息推送,
        }
        return dto;
    }

    /**
     * 查询设备实时状态
     *
     * @param deviceId
     * @param spId
     * @return
     */
    protected DeviceState getStateByDeviceId(String deviceId, String spId) {
        LambdaQueryWrapper<DeviceState> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DeviceState::getDeviceId, deviceId)
                .eq(DeviceState::getIsDeleted, Constants.IS_DELETED_FALSE)
                .eq(DeviceState::getSpId, spId);
        DeviceState deviceState = deviceStateMapper.selectOne(queryWrapper);
        return deviceState;
    }

    /**
     * 根据设备状态变化,进行消息通知
     *
     * @param dto
     */
    protected void checkDeviceState(ReportNotifyDTO dto,Map<String,Dtu> dtuMap) {
        log.info("checkDeviceState :"+dto.toString());
        if (browserNotifyService == null) {
            browserNotifyService = ApplicationContextUtils.getBean(BrowserNotifyService.class);
        }
        if (resetlogService == null) {
            resetlogService = ApplicationContextUtils.getBean(ResetlogService.class);
        }
        if (warningDataService == null) {
            warningDataService = ApplicationContextUtils.getBean(WarningDataServiceImpl.class);
        }
        if (zjWifiService == null) {
            zjWifiService = ApplicationContextUtils.getBean(ZjWifiService.class);
        }
        DataReportRequest request = dto.getRequest();
        Dtu dtu = dto.getDtu();
        Dtu imei = dtuMap.get(dtu.getIMEI());
        if (null == imei || null == imei.getId()) {
            imei = equipmentService.getDeviceByImei(dtu.getIMEI(), dtu.getSpId());
        }
        log.info("设备信息：{}", imei);
        DeviceState deviceState = dto.getDeviceState();
        DeviceState prepareDeviceState = dto.getPrepareDeviceState();
        ReceiverValve receiverValve = dto.getReceiverValve();

        boolean zjBrokenFlag = false;
        String valveStatusDesc = request.getValveStatusDesc() == null ? "" : request.getValveStatusDesc();
        String zjBrokenStatusInfo = "";
        boolean isIgnoreValveBroken = false;
        //接收器和电磁阀故障
        if (Constants.ZJ_EQUIPMENT_FROM.equals(dtu.getEquipmentFrom())) {
            isIgnoreValveBroken = checkZjWifiBrokenIsIgnore(valveStatusDesc,receiverValve);
            //接收器离线推送，不受故障影响
            if (dto.getPrepareDeviceState() != null && dto.getPrepareReceiverValve() != null &&
                    VALVE_CONNECTION_0.equals(dto.getPrepareReceiverValve().getReceiverStatus()) &&
                    (receiverValve == null || VALVE_CONNECTION_1.equals(receiverValve.getReceiverStatus()))) {
                zjWifiService.pushMsg(dtu, 7);
            }
            //上报前为空或上报前非故障，并且上报后是故障
            if ((receiverValve == null || !VALVE_WORK_STATUS_BROKEN.equals(receiverValve.getBrokenStatus())) &&
                    VALVE_WORK_STATUS_1.equals(request.getValveWorkStatus()) && dto.getPrepareReceiverValve() != null) {
                if (  !StringUtils.isEmpty(valveStatusDesc) ) {
                    if (valveStatusDesc.contains(VALVE_BROKEN_STATUS_70.toString())) {
                        zjBrokenStatusInfo = VALVE_BROKEN_STATUS_70_INFO + ";";
                    }
                    if (!isIgnoreValveBroken) {
                        if (valveStatusDesc.contains(VALVE_BROKEN_STATUS_71.toString())) {
                            zjBrokenStatusInfo = zjBrokenStatusInfo + VALVE_BROKEN_STATUS_71_INFO + ";";
                        }
                        if (valveStatusDesc.contains(VALVE_BROKEN_STATUS_72.toString())) {
                            zjBrokenStatusInfo = zjBrokenStatusInfo + VALVE_BROKEN_STATUS_72_INFO + ";";
                            //上报前是非电磁阀短路，当前接收器状态阀故障(电磁阀短路)
                            if (!receiverValve.getBrokenStatusInfo().contains("电磁阀短路")) {
                                zjWifiService.pushMsg(dtu, 9);
                            }
                        }
                        if (valveStatusDesc.contains(VALVE_BROKEN_STATUS_73.toString())) {
                            zjBrokenStatusInfo = zjBrokenStatusInfo + VALVE_BROKEN_STATUS_73_INFO + ";";
                            //上报前是非电磁阀开，当前接收器状态阀断开(电磁阀开路)
                            if (!receiverValve.getBrokenStatusInfo().contains("电磁阀开路")) {
                                zjWifiService.pushMsg(dtu, 10);
                            }
                        }
                        if (valveStatusDesc.contains(VALVE_BROKEN_STATUS_74.toString())) {
                            zjBrokenStatusInfo = zjBrokenStatusInfo + VALVE_BROKEN_STATUS_74_INFO + ";";
                            //低于2.4V：电磁阀状态：欠压、关阀、离线三个状态同时存在
                            if (valveStatusDesc.contains(VALVE_BROKEN_STATUS_71.toString()) && VALVE_STATUS_CLOSE.equals(request.getValveStatus())) {
                                zjWifiService.pushMsg(dtu, 5);
                            } else {
                                //低于2.7v：电磁阀状态：欠压
                                zjWifiService.pushMsg(dtu, 4);
                            }
                        }
                    }
                    if (!zjBrokenStatusInfo.equals(receiverValve.getBrokenStatusInfo())) {
                        log.info("新故障：" + zjBrokenStatusInfo);
                        log.info("旧故障：" + receiverValve.getBrokenStatusInfo());
                        log.info("两次电磁阀故障不相同，则故障记录");
                        zjBrokenFlag = true;
                    }
                }
            }
        }
        //判断故障的逻辑(上报前状态是故障时，最新上报也是故障，上报前故障原因 != 最新上报的故障原因)
        boolean brokenFlag = false;
        boolean alertFlag = false;
        //设备发生报警后紧接发生故障，没有故障的消息推送，需要增加消息推送
        if (DEVICE_STATUS_2.equals(prepareDeviceState.getDeviceStatus()) ||
                DEVICE_STATUS_3.equals(prepareDeviceState.getDeviceStatus()) ||
                DEVICE_STATUS_6.equals(prepareDeviceState.getDeviceStatus())) {
            alertFlag = true;
        }
        if ((alertFlag || DEVICE_STATUS_4.equals(prepareDeviceState.getDeviceStatus())) && DEVICE_STATUS_4.equals(deviceState.getDeviceStatus()) &&
                !deviceState.getDeviceStatusInfo().equals(prepareDeviceState.getDeviceStatusInfo())) {
            brokenFlag = true;
        }
        //前是故障，后是故障，并且故障内容一样，则不记录和推送
        boolean isBrokenFlag = true;
        if (prepareDeviceState.getIsBroken() != null && prepareDeviceState.getBrokenStatusInfo() != null &&
                deviceState.getIsBroken() != null && deviceState.getIsBroken() && prepareDeviceState.getIsBroken() &&
                prepareDeviceState.getBrokenStatusInfo().equals(deviceState.getBrokenStatusInfo())) {
            isBrokenFlag = false;
        }
        if ((DEVICE_STATUS_2.equals(deviceState.getDeviceStatus()) || DEVICE_STATUS_3.equals(deviceState.getDeviceStatus())
                || DEVICE_STATUS_6.equals(deviceState.getDeviceStatus()))
                && DEVICE_STATUS_1.equals(prepareDeviceState.getDeviceStatus())) {
            Resetlog resetLog = createResetLog(dtu, request);
            resetlogService.insert(resetLog);
            List<BrowserNotifyItemRequest> notifyRequest = prepareBrowserNotifyItem(prepareDeviceState, dtu, BrowserNotifyReason.AlertRecover);
            log.info("报警恢复推送开始-resetLog:{} ", JSONObject.toJSONString(resetLog));
            log.info("notifyRequest:{}", JSONObject.toJSONString(notifyRequest));
            notifyRequest.forEach(browserNotifyItemRequest -> {
                browserNotifyItemRequest.setEquipmentFrom(dtu.getEquipmentFrom());
                if (Constants.ZJ_EQUIPMENT_FROM.equals(dtu.getEquipmentFrom())) {
                    browserNotifyItemRequest.setValveStatus(request.getValveStatus() == 0 ? "正常" : "关闭");
                    browserNotifyItemRequest.setReceiverStatus(request.getValveConnection() == 0 ? "离线" : "正常");
                }
            });
            consoleNotify(notifyRequest);
            wechatNotify(notifyRequest);
            HistoryAlarm alarm = new HistoryAlarm();
            alarm.setCreatedAt(request.getReportDate());
            alarm.setIMEI(dtu.getIMEI());
            alarm.setSpId(dtu.getSpId());
            alarm.setConsumerId(imei.getConsumerId());
            log.info("handleWarningData-alarm:{},{}", JSONObject.toJSONString(alarm), 1);
            warningDataService.handleWarningData(alarm, 1);
            alarmBrokenAutoHandel(alarm,0);
            smartKitchenService.syncAlarmStatusNotice(dtu,0);
        } else if (DEVICE_STATUS_4.equals(deviceState.getDeviceStatus())
                && DEVICE_STATUS_1.equals(prepareDeviceState.getDeviceStatus())) {
            Resetlog resetLog = createResetLog(dtu, request);
            resetlogService.insert(resetLog);
            List<BrowserNotifyItemRequest> notifyRequest = prepareBrowserNotifyItem(prepareDeviceState, dtu, BrowserNotifyReason.BrokenRecover);
            log.info("故障恢复推送开始-resetLog:{}", JSONObject.toJSONString(resetLog));
            log.info("notifyRequest:{}", JSONObject.toJSONString(notifyRequest));
            notifyRequest.forEach(browserNotifyItemRequest -> {
                browserNotifyItemRequest.setEquipmentFrom(dtu.getEquipmentFrom());
                if (Constants.ZJ_EQUIPMENT_FROM.equals(dtu.getEquipmentFrom())) {
                    browserNotifyItemRequest.setValveStatus(request.getValveStatus() == 0 ? "正常" : "关闭");
                    browserNotifyItemRequest.setReceiverStatus(request.getValveConnection() == 0 ? "离线" : "正常");
                }
            });
            consoleNotify(notifyRequest);
            wechatNotify(notifyRequest);
            HistoryBroken historyBroken = new HistoryBroken();
            historyBroken.setDeviceId(deviceState.getDeviceId());
            historyBroken.setIMEI(dtu.getIMEI());
            historyBroken.setSpId(dtu.getSpId());
            historyBroken.setConsumerId(imei.getConsumerId());
            alarmBrokenAutoHandel(historyBroken,1);
            // deviceState.getDeviceStatus()不为null,当设备不存在state表时, 会预设一个deviceState.getDeviceStatus()正常
            // 当设备 报警且前后状态不一致时，并且报警前的状态是非报警,则推送
        } else if (!deviceState.getDeviceStatus().equals(prepareDeviceState.getDeviceStatus()) &&
                (DEVICE_STATUS_2.equals(prepareDeviceState.getDeviceStatus()) ||
                        DEVICE_STATUS_3.equals(prepareDeviceState.getDeviceStatus()) ||
                        DEVICE_STATUS_6.equals(prepareDeviceState.getDeviceStatus())) &&
                !DEVICE_STATUS_2.equals(deviceState.getDeviceStatus()) &&
                !DEVICE_STATUS_3.equals(deviceState.getDeviceStatus()) &&
                !DEVICE_STATUS_6.equals(deviceState.getDeviceStatus())) {
            // 报警
            HistoryAlarm alarm = new HistoryAlarm();
            alarm.setDeviceId(deviceState.getDeviceId());
            alarm.setIMEI(dtu.getIMEI());
            alarm.setConcentration(prepareDeviceState.getConcentration());
            alarm.setCreatedAt(request.getReportDate());
            alarm.setSpId(dtu.getSpId());
            alarm.setConsumerId(imei.getConsumerId());
            alarm.setDeviceStatus(prepareDeviceState.getDeviceStatus());
            if (VALVE_CONNECTION_0.equals(request.getValveConnection())) {
                alarm.setReceiverStatus(RECEIVER_STATUS_OFFLINE);
            } else {
                alarm.setReceiverStatus(RECEIVER_STATUS_NORMAL);
            }
            if (VALVE_STATUS_0.equals(request.getValveStatus())) {
                alarm.setValveStatus(VALVE_STATUS_OPEN);
            } else if (VALVE_STATUS_1.equals(request.getValveStatus())) {
                alarm.setValveStatus(VALVE_STATUS_CLOSE);
            }
            //故障并且未欠压，则记录接收器故障信息
            if (VALVE_WORK_STATUS_1.equals(request.getValveWorkStatus())) {
                alarm.setValveBrokenStatus(VALVE_WORK_STATUS_BROKEN);
                alarm.setValveBrokenInfo(zjBrokenStatusInfo);
            }
            if (historyAlarmMapper == null) {
                historyAlarmMapper = ApplicationContextUtils.getBean(HistoryAlarmMapper.class);
            }
            if (historyAlarmService == null) {
                historyAlarmService = ApplicationContextUtils.getBean(HistoryAlarmServiceImpl.class);
            }
            if (workOrderHistoryMapper == null) {
                workOrderHistoryMapper = ApplicationContextUtils.getBean(WorkOrderHistoryMapper.class);
            }
            String alarmIMEI = alarm.getIMEI();
            if (alarmIMEI.contains("-"))alarmIMEI=alarmIMEI.split("-")[0];
            LambdaQueryWrapper<WorkOrderHistory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.or().eq(WorkOrderHistory::getIsDeleted,0)
                    .eq(WorkOrderHistory::getDeviceId,alarmIMEI)
                    .in(WorkOrderHistory::getOrderType,1,11).eq(WorkOrderHistory::getHandleStatus,0)
                    .orderByDesc(WorkOrderHistory::getCreatedAt);
            List<WorkOrderHistory> workOrderHistories = workOrderHistoryMapper.selectList(queryWrapper);
            log.info("appealIntallRecord-workOrderHistories:{}",JSONObject.toJSON(workOrderHistories));
            LambdaQueryWrapper<WorkOrderHistory> queryNew = new LambdaQueryWrapper<>();
            queryNew.or().eq(WorkOrderHistory::getIsDeleted,0)
                    .likeRight(WorkOrderHistory::getNewDeviceId,alarmIMEI)
                    .eq(WorkOrderHistory::getHandleStatus,0)
                    .orderByDesc(WorkOrderHistory::getCreatedAt);
            List<WorkOrderHistory> newImeis = workOrderHistoryMapper.selectList(queryNew);
            log.info("appealIntallRecord-newImeis:{}",JSONObject.toJSON(newImeis));

            LambdaQueryWrapper<WorkOrderHistory> lqw = new LambdaQueryWrapper<>();
            lqw.or().eq(WorkOrderHistory::getIsDeleted,0)
                    .eq(WorkOrderHistory::getDeviceId,alarmIMEI)
                    .in(WorkOrderHistory::getOrderType,8,9,12,13) //点火工单调试，安检单调试
                    .eq(WorkOrderHistory::getHandleStatus,0)
                    .orderByDesc(WorkOrderHistory::getCreatedAt);
            List<WorkOrderHistory> sparkOrderHistories = workOrderHistoryMapper.selectList(lqw);
            log.info("appealSparkOrder-workOrderHistories:{}",JSONObject.toJSON(sparkOrderHistories));

            historyAlarmMapper.insert(alarm);
            if (!CollectionUtils.isEmpty(workOrderHistories)||!CollectionUtils.isEmpty(newImeis)){
                WorkOrderHistory workOrderHistory = new WorkOrderHistory();
                workOrderHistory.setSpId(alarm.getSpId());
                //处理未完成工单报警数据
                historyAlarmService.appealIntallRecord(workOrderHistory,alarm.getId(),0);
            }
            if (!CollectionUtils.isEmpty(sparkOrderHistories)){
                appealLogService.appealSparkRecord(alarm.getSpId(),alarm.getId(),0);
            }

            List<BrowserNotifyItemRequest> notifyRequest = prepareBrowserNotifyItem(prepareDeviceState, dtu, BrowserNotifyReason.Alert);
            log.info("报警推送开始-alarm:{}", JSONObject.toJSONString(alarm));
            log.info("notifyRequest:{}", JSONObject.toJSONString(notifyRequest));
            notifyRequest.forEach(browserNotifyItemRequest -> {
                browserNotifyItemRequest.setEquipmentFrom(dtu.getEquipmentFrom());
                if (Constants.ZJ_EQUIPMENT_FROM.equals(dtu.getEquipmentFrom())) {
                    browserNotifyItemRequest.setValveStatus(request.getValveStatus() == 0 ? "正常" : "关闭");
                    browserNotifyItemRequest.setReceiverStatus(request.getValveConnection() == 0 ? "离线" : "正常");
                }
            });
            consoleNotify(notifyRequest);
            wechatNotify(notifyRequest);
            zjWifiService.pushMsg(dtu, 1);
            log.info("handleWarningData-alarm:{},{}", JSONObject.toJSONString(alarm), 0);
            warningDataService.handleWarningData(alarm, 0);
            smartKitchenService.syncAlarmStatusNotice(dtu,1);
        } else if ((!DEVICE_STATUS_4.equals(deviceState.getDeviceStatus()) || brokenFlag) &&   // 当此前状态不为故障（或当前状态是故障，但是故障原因不同），并且当前故障时,推送
                DEVICE_STATUS_4.equals(prepareDeviceState.getDeviceStatus()) && isBrokenFlag) {
            // 特殊场景处理
            specialSceneAlarmBrokenAutoHandel(deviceState.getDeviceStatus(),
                    dtu.getIMEI(),
                    dtu.getSpId(),
                    deviceState.getDeviceId(),
                    imei.getConsumerId()
            );
            // 故障
            HistoryBroken broken = new HistoryBroken();
            broken.setDeviceId(deviceState.getDeviceId());
            broken.setIMEI(dtu.getIMEI());
            broken.setReason(prepareDeviceState.getDeviceStatusInfo());
            broken.setCreatedAt(request.getReportDate());
            broken.setSpId(dtu.getSpId());
            broken.setConsumerId(imei.getConsumerId());
            if (VALVE_CONNECTION_0.equals(request.getValveConnection())) {
                broken.setReceiverStatus(RECEIVER_STATUS_OFFLINE);
            } else {
                broken.setReceiverStatus(RECEIVER_STATUS_NORMAL);
            }
            if (VALVE_STATUS_0.equals(request.getValveStatus())) {
                broken.setValveStatus(VALVE_STATUS_OPEN);
            } else if (VALVE_STATUS_1.equals(request.getValveStatus())) {
                broken.setValveStatus(VALVE_STATUS_CLOSE);
            }
            //故障并且未欠压，则记录接收器故障信息
            if (VALVE_WORK_STATUS_1.equals(request.getValveWorkStatus())) {
                broken.setValveBrokenStatus(VALVE_WORK_STATUS_BROKEN);
                broken.setValveBrokenInfo(zjBrokenStatusInfo);
            }
            if (historyBrokenMapper == null) {
                historyBrokenMapper = ApplicationContextUtils.getBean(HistoryBrokenMapper.class);
            }
            if (historyAlarmService == null) {
                historyAlarmService = ApplicationContextUtils.getBean(HistoryAlarmServiceImpl.class);
            }
            if (workOrderHistoryMapper == null) {
                workOrderHistoryMapper = ApplicationContextUtils.getBean(WorkOrderHistoryMapper.class);
            }
            String alarmIMEI = broken.getIMEI();
            if (alarmIMEI.contains("-"))alarmIMEI=alarmIMEI.split("-")[0];
            LambdaQueryWrapper<WorkOrderHistory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.or().eq(WorkOrderHistory::getIsDeleted,0)
                    .likeRight(WorkOrderHistory::getDeviceId,alarmIMEI)
                    .in(WorkOrderHistory::getOrderType,1,11).eq(WorkOrderHistory::getHandleStatus,0)
                    .orderByDesc(WorkOrderHistory::getCreatedAt);
            List<WorkOrderHistory> workOrderHistories = workOrderHistoryMapper.selectList(queryWrapper);
            log.info("appealIntallRecord-workOrderHistories:{}",JSONObject.toJSON(workOrderHistories));
            LambdaQueryWrapper<WorkOrderHistory> queryNew = new LambdaQueryWrapper<>();
            queryNew.or().eq(WorkOrderHistory::getIsDeleted,0)
                    .likeRight(WorkOrderHistory::getNewDeviceId,alarmIMEI)
                    .eq(WorkOrderHistory::getHandleStatus,0)
                    .orderByDesc(WorkOrderHistory::getCreatedAt);
            List<WorkOrderHistory> newImeis = workOrderHistoryMapper.selectList(queryNew);
            log.info("appealIntallRecord-newImeis:{}",JSONObject.toJSON(newImeis));

            LambdaQueryWrapper<WorkOrderHistory> lqw = new LambdaQueryWrapper<>();
            lqw.or().eq(WorkOrderHistory::getIsDeleted,0)
                    .eq(WorkOrderHistory::getDeviceId,alarmIMEI)
                    .in(WorkOrderHistory::getOrderType,8,9,12,13) //点火工单调试，安检单调试
                    .eq(WorkOrderHistory::getHandleStatus,0)
                    .orderByDesc(WorkOrderHistory::getCreatedAt);
            List<WorkOrderHistory> sparkOrderHistories = workOrderHistoryMapper.selectList(lqw);
            log.info("appealSparkOrder-workOrderHistories:{}",JSONObject.toJSON(sparkOrderHistories));

            historyBrokenMapper.insert(broken);
            if (!CollectionUtils.isEmpty(workOrderHistories)||!CollectionUtils.isEmpty(newImeis)){
                WorkOrderHistory workOrderHistory = new WorkOrderHistory();
                workOrderHistory.setSpId(broken.getSpId());
                //处理未完成工单报警数据
                historyAlarmService.appealIntallRecord(workOrderHistory,broken.getId(),1);
            }
            if (!CollectionUtils.isEmpty(sparkOrderHistories)){
                appealLogService.appealSparkRecord(broken.getSpId(),broken.getId(),1);
            }

            List<BrowserNotifyItemRequest> notifyRequest = prepareBrowserNotifyItem(prepareDeviceState, dtu, BrowserNotifyReason.Broken);
            log.info("故障推送开始-alarm:{} }", JSONObject.toJSONString(broken));
            log.info("notifyRequest:{}", JSONObject.toJSONString(notifyRequest));
            //故障
            notifyRequest.forEach(browserNotifyItemRequest -> {
                browserNotifyItemRequest.setEquipmentFrom(dtu.getEquipmentFrom());
                if (Constants.ZJ_EQUIPMENT_FROM.equals(dtu.getEquipmentFrom())) {
                    browserNotifyItemRequest.setValveStatus(request.getValveStatus() == 0 ? "正常" : "关闭");
                    browserNotifyItemRequest.setReceiverStatus(request.getValveConnection() == 0 ? "离线" : "正常");
                }
            });
            consoleNotify(notifyRequest);
            wechatNotify(notifyRequest);
            smartKitchenService.handleBrokenSyncAlarmStatusNotice(dtu,deviceState,prepareDeviceState);
            log.info("smsNotify-start:{},{}", JSONObject.toJSONString(deviceState), JSONObject.toJSONString(prepareDeviceState));
            //设备故障首次提醒
            if (prepareDeviceState.getDeviceStatus() != null
                    && !prepareDeviceState.getDeviceStatus().equals(deviceState.getDeviceStatus())) {
                smsNotify(notifyRequest, dtu);
                wechatFirstBrokenNotify(notifyRequest);
            }
            if ( StringUtils.isNotEmpty(broken.getReason()) && broken.getReason().contains("使用寿命到期")) {
                log.info("设备信息的具体值为:{}",dtu);
                if (StringUtils.equals(EquipmentType.HOME_GAS_DETECTOR.getCode(), dtu.getEquipmentType())) {
                    zjWifiService.pushMsg(dtu, 3);
                }else if (StringUtils.equals(EquipmentType.GAS_ALARM_CONTROLLER.getCode(), dtu.getEquipmentType())){
                    zjWifiService.pushMsg(dtu, 12);
                }else {
                    zjWifiService.pushMsg(dtu, 11);
                }
            } else {
                zjWifiService.pushMsg(dtu, 2);
            }
        } else if (zjBrokenFlag) {
            // 电磁阀故障
            HistoryBroken broken = new HistoryBroken();
            broken.setDeviceId(deviceState.getDeviceId());
            broken.setIMEI(dtu.getIMEI());
            broken.setReason("");
            broken.setCreatedAt(request.getReportDate());
            broken.setConsumerId(imei.getConsumerId());
            broken.setSpId(dtu.getSpId());
            if (VALVE_CONNECTION_0.equals(request.getValveConnection())) {
                broken.setReceiverStatus(RECEIVER_STATUS_OFFLINE);
            } else {
                broken.setReceiverStatus(RECEIVER_STATUS_NORMAL);
            }
            if (VALVE_STATUS_0.equals(request.getValveStatus())) {
                broken.setValveStatus(VALVE_STATUS_OPEN);
            } else if (VALVE_STATUS_1.equals(request.getValveStatus())) {
                broken.setValveStatus(VALVE_STATUS_CLOSE);
            }
            //故障并且未欠压，则记录接收器故障信息
            if (VALVE_WORK_STATUS_1.equals(request.getValveWorkStatus())) {
                broken.setValveBrokenStatus(VALVE_WORK_STATUS_BROKEN);
                broken.setValveBrokenInfo(zjBrokenStatusInfo);
            }
            if (historyBrokenMapper == null) {
                historyBrokenMapper = ApplicationContextUtils.getBean(HistoryBrokenMapper.class);
            }
            log.info("记录电磁阀故障：" + broken.toString());
            historyBrokenMapper.insert(broken);
        }
        //上报前是电磁阀开，最新上报了电磁阀关闭，需要推送消息
        if (dto.getReceiverValve() != null && VALVE_STATUS_0.equals(dto.getReceiverValve().getValveStatus()) &&
                VALVE_STATUS_1.equals(request.getValveStatus()) && !isIgnoreValveBroken) {
            zjWifiService.pushMsg(dtu, 8);
        }
    }

    /**
     * 特殊场景的自动恢复【故障->报警->报警恢复】
     * @param deviceStatus
     * @param imei
     * @param spId
     * @param deviceId
     * @param consumerId
     */
    public void specialSceneAlarmBrokenAutoHandel(Integer deviceStatus,
                                                  String imei,
                                                  String spId,
                                                  String deviceId,
                                                  Integer consumerId){
        if( DEVICE_STATUS_2.equals(deviceStatus) ||
                DEVICE_STATUS_3.equals(deviceStatus) ){
            //取本次上报之前的一条报警记录
            HistoryAlarm alarm = new HistoryAlarm();
            alarm.setIMEI(imei);
            alarm.setSpId(spId);
            alarm.setConsumerId(consumerId);
            alarmBrokenAutoHandel(alarm,0);

            HistoryBroken historyBroken = new HistoryBroken();
            historyBroken.setDeviceId(deviceId);
            historyBroken.setIMEI(imei);
            historyBroken.setSpId(spId);
            historyBroken.setConsumerId(consumerId);
            alarmBrokenAutoHandel(historyBroken,1);
        }
    }

    /**
     * 报警恢复，故障恢复自动处理报警，故障记录
     * @param alarmBrokenInfo
     * @param type 0:报警 1:故障
     */
    public void alarmBrokenAutoHandel(Object alarmBrokenInfo, int type){
        try{
            if (historyAlarmService == null) {
                historyAlarmService = ApplicationContextUtils.getBean(HistoryAlarmServiceImpl.class);
            }
            historyAlarmService.alarmBrokenAutoHandelWhenRecovery(alarmBrokenInfo,type);
        }catch (Exception e){
            log.error("alarmBrokenAutoHandel error",e);
        }

    }


    /**
     * 最后,根据workStatus设置设备开关机状态,并通知
     *
     * @param prepareRecordController
     * @param prepareDeviceState
     * @param dtu
     */
    protected ReportNotifyOfflineDTO updateDeviceOffline(DataReportRequest request, RecordController prepareRecordController, DeviceState prepareDeviceState, Dtu dtu) {
        if (browserNotifyService == null) {
            browserNotifyService = ApplicationContextUtils.getBean(BrowserNotifyService.class);
        }
        if (equipmentService == null) {
            equipmentService = ApplicationContextUtils.getBean(EquipmentService.class);
        }


        ReportNotifyOfflineDTO offlineDTO = new ReportNotifyOfflineDTO();
        if (WORK_STATUS_1.equals(prepareRecordController.getWorkStatus())) {
            //查询设备及关联探测器
            List<String> deviceIds = new ArrayList<>();
            deviceIds.add(dtu.getIMEI());
            //为控制器且data部分有数据时;
            if (EquipmentType.GAS_ALARM_CONTROLLER.getCode().equals(dtu.getEquipmentType())
                    && CollectionUtil.isNotEmpty(request.getData())) {
                for (DataReportDataRequest dataRequest : request.getData()) {
                    deviceIds.add(dtu.getIMEI() + "-1-" + dataRequest.getSno());
                }
            }
            log.info("数据上报的所有设备号:{}", JSONObject.toJSONString(deviceIds));

            if (CollectionUtil.isNotEmpty(deviceIds)) {
                for (String deviceId : deviceIds) {
                    DeviceState deviceState = new DeviceState();
                    deviceState.setDeviceStatus(DEVICE_STATUS_1);
                    deviceState.setDeviceStatusInfo(DEVICE_STATUS_1_INFO);
                    deviceState.setLastReportTime(new Date());

                    QueryWrapper<DeviceState> queryWrapper = new QueryWrapper<>();
                    queryWrapper.lambda().eq(DeviceState::getDeviceId, deviceId)
                            .eq(DeviceState::getSpId, dtu.getSpId())
                            .eq(DeviceState::getIsDeleted, false);

                    //当设备第一次上报
                    DeviceState oldDeviceState = deviceStateMapper.selectOne(queryWrapper);
                    if (oldDeviceState != null) {
                        deviceState.setId(oldDeviceState.getId());
                        deviceStateMapper.updateById(deviceState);
                    } else {
                        log.info("设备 id:{} 为第一次上报,开机信息", dtu.getId());
                        deviceState.setDeviceId(deviceId);
                        deviceState.setSpId(dtu.getSpId());
                        deviceStateMapper.insert(deviceState);
                    }
                }

                offlineDTO.setPrepareDeviceState(prepareDeviceState);
                offlineDTO.setDtu(dtu);
                offlineDTO.setReason(BrowserNotifyReason.PowerOn);
                offlineDTO.setChange(true);
                
            } else {
                log.error("deviceIds return null, dtu中不存在 deviceId:{} ", prepareRecordController.getDeviceId());
                throw new BizException(1009, "dtu中不存在 deviceId:" + prepareRecordController.getDeviceId());
            }
        } else if (WORK_STATUS_2.equals(prepareRecordController.getWorkStatus()) || WORK_STATUS_4.equals(prepareRecordController.getWorkStatus())) {
            log.info("设备workStatus:关机,关联的所有设备状态更新为离线.");
            //掉电 设备整体离线
            //查询设备及所有关联探测器
            List<Dtu> dtuList = equipmentService.getAllDtuById(prepareRecordController.getDeviceId());
            List<String> deviceIds = dtuList.stream().map(Dtu::getId).collect(Collectors.toList());

            DeviceState DEVICE_STATE = new DeviceState();
            DEVICE_STATE.setDeviceStatus(DEVICE_STATUS_0);
            DEVICE_STATE.setDeviceStatusInfo(WORK_STATUS_2_INFO);
            DEVICE_STATE.setLastReportTime(new Date());
            QueryWrapper<DeviceState> queryWrapper = new QueryWrapper<>();
            if (CollectionUtil.isNotEmpty(deviceIds)) {
                queryWrapper.lambda().in(DeviceState::getDeviceId, deviceIds)
                        .eq(DeviceState::getIsDeleted, IS_DELETED_0);
                deviceStateMapper.update(DEVICE_STATE, queryWrapper);
                offlineDTO.setPrepareDeviceState(prepareDeviceState);
                offlineDTO.setDtu(dtu);
                offlineDTO.setReason(BrowserNotifyReason.PowerOff);
                offlineDTO.setChange(true);
                
            } else {
                log.error("deviceIds return null, dtu中不存在 deviceId:{} ", prepareRecordController.getDeviceId());
                throw new BizException(1009, "dtu中不存在 deviceId:" + prepareRecordController.getDeviceId());
            }
        } else {
            offlineDTO.setChange(false);
        }
        return offlineDTO;
    }


    protected void offlineNotify(ReportNotifyOfflineDTO offlineDTO) {
        if (BrowserNotifyReason.PowerOn == offlineDTO.getReason()) {
            List<BrowserNotifyItemRequest> notifyRequest = prepareBrowserNotifyItem(offlineDTO.getPrepareDeviceState(), offlineDTO.getDtu(), BrowserNotifyReason.PowerOn);
            log.info("设备:{}上电,更新状态, 开始消息推送", offlineDTO.getPrepareDeviceState().getDeviceId());
            log.info(" notifyRequest:{}", JSONObject.toJSONString(notifyRequest));
            notifyRequest.forEach(browserNotifyItemRequest -> {
                browserNotifyItemRequest.setEquipmentFrom(offlineDTO.getDtu().getEquipmentFrom());
                if (Constants.ZJ_EQUIPMENT_FROM.equals(offlineDTO.getDtu().getEquipmentFrom()) && offlineDTO.getReceiverValve() != null) {
                    browserNotifyItemRequest.setValveStatus(offlineDTO.getReceiverValve().getValveStatus() == 0 ? "正常" : "关闭");
                    browserNotifyItemRequest.setReceiverStatus(offlineDTO.getReceiverValve().getReceiverStatus() == 0 ? "离线" : "正常");
                }
            });
            consoleNotify(notifyRequest);
            wechatNotify(notifyRequest);
            Dtu dtu = offlineDTO.getDtu();
            log.info(" dtu设备的值为:{}", dtu);
            if (dtu != null) {
                //获取数据库连接
                InfluxDBConnect influxDBConnect = influxDBConfiguration.getInfluxDBConnect();
                HashMap<String, String> tag = new HashMap<>();
                HashMap<String, Object> field = new HashMap<>();
                tag.put("DtuId", dtu.getId());
                tag.put("Path", dtu.getPath());
                field.put("Ccid", dtu.getIccid());
                field.put("ConsumerId", dtu.getConsumerId());
                field.put("DtuType", Integer.parseInt(dtu.getEquipmentManufacturer()));
                field.put("Offline", false);
                field.put("Version",1000);
                influxDBConnect.insert("PowerLogAsDtu", tag, field);
            }
        } else if (BrowserNotifyReason.PowerOff == offlineDTO.getReason()) {
            List<BrowserNotifyItemRequest> notifyRequest = prepareBrowserNotifyItem(offlineDTO.getPrepareDeviceState(), offlineDTO.getDtu(), BrowserNotifyReason.PowerOff);
            log.info("设备:{}掉电,更新离线状态", offlineDTO.getPrepareDeviceState().getDeviceId());
            log.info("开始关机消息推送 notifyRequest:{}", notifyRequest);
            notifyRequest.forEach(browserNotifyItemRequest -> {
                browserNotifyItemRequest.setEquipmentFrom(offlineDTO.getDtu().getEquipmentFrom());
                if (Constants.ZJ_EQUIPMENT_FROM.equals(offlineDTO.getDtu().getEquipmentFrom()) && offlineDTO.getReceiverValve() != null) {
                    browserNotifyItemRequest.setValveStatus(offlineDTO.getReceiverValve().getValveStatus() == 0 ? "正常" : "关闭");
                    browserNotifyItemRequest.setReceiverStatus(offlineDTO.getReceiverValve().getReceiverStatus() == 0 ? "离线" : "正常");
                }
            });
            consoleNotify(notifyRequest);
            wechatNotify(notifyRequest);
            Dtu dtu = offlineDTO.getDtu();
            if (dtu != null) {
                //获取数据库连接
                InfluxDBConnect influxDBConnect = influxDBConfiguration.getInfluxDBConnect();
                HashMap<String, String> tag = new HashMap<>();
                HashMap<String, Object> field = new HashMap<>();
                tag.put("DtuId", dtu.getId());
                tag.put("Path", dtu.getPath());
                field.put("Ccid", dtu.getIccid());
                field.put("ConsumerId", dtu.getConsumerId());
                field.put("DtuType", Integer.parseInt(dtu.getEquipmentManufacturer()));
                field.put("Offline", true);
                field.put("Version",1000);
                influxDBConnect.insert("PowerLogAsDtu", tag, field);
            }
//            if (zjWifiService == null) {
//                zjWifiService = ApplicationContextUtils.getBean(ZjWifiService.class);
//            }
//            zjWifiService.pushMsg(offlineDTO.getDtu(),6);
        }

    }

    protected void powerRecord(Dtu dtu) {
        if (dtu != null) {
            DeviceState deviceState = getStateByDeviceId(dtu.getIMEI(), dtu.getSpId());
            if (deviceState != null && deviceState.getDeviceStatus() != null
                && deviceState.getDeviceStatus() == 0) {
                log.info("powerRecord-deviceState开机记录：{}", deviceState);
                //获取数据库连接
                InfluxDBConnect influxDBConnect = influxDBConfiguration.getInfluxDBConnect();
                HashMap<String, String> tag = new HashMap<>();
                HashMap<String, Object> field = new HashMap<>();
                tag.put("DtuId", dtu.getId());
                tag.put("Path", dtu.getPath());
                field.put("Ccid", dtu.getIccid());
                field.put("ConsumerId", dtu.getConsumerId());
                field.put("DtuType", Integer.parseInt(dtu.getEquipmentManufacturer()));
                field.put("Offline", false);
                field.put("Version",1000);
                influxDBConnect.insert("PowerLogAsDtu", tag, field);
            }
        }

    }


    protected Resetlog createResetLog(Dtu dtu, DataReportRequest request) {
        Resetlog resetlog = new Resetlog();
        String sub = StringUtils.substringAfter(dtu.getIMEI(), "-");
        resetlog.setTime(request.getReportDate());
        resetlog.setDtuId(StringUtils.substringBefore(dtu.getIMEI(), "-"));
        resetlog.setSubIdentifier(StringUtils.isEmpty(sub) ? "1-1" : sub);
        //根据spId换path
        if (departmentService == null) {
            departmentService = ApplicationContextUtils.getBean(DepartmentService.class);
        }
        String path = departmentService.getPath(dtu.getSpId());
        resetlog.setPath(path);
        resetlog.setDepartmentId(0);
        resetlog.setConsumerId(dtu.getConsumerId());
        resetlog.setInspectorId(0);
        resetlog.setInspectTime(new Date());
        return resetlog;
    }


    protected List<Dtu> getDtuByDeviceCode(String deviceCode) {
        if (dtuMapper == null) {
            dtuMapper = ApplicationContextUtils.getBean(DtuMapper.class);
        }
        return dtuMapper.selectBindByDeviceCode(deviceCode);
    }

    protected void setStatusInfo(Integer controllerStatus, Integer detectorStatus, DeviceState preDeviceState) {
        log.info("setStatusInfo start preDeviceState:" + preDeviceState.toString());
        //入参两类,  1.有控制器状态的  2.修改探测器状态: 没有为null的;
        // preDeviceState 传入时,DeviceStatus都没有值
        if (controllerStatus != null) {
            if (DETECTOR_STATUS_0.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_1);
                preDeviceState.setDeviceStatusInfo(DEVICE_STATUS_1_INFO);
            } else if (DETECTOR_STATUS_17.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(DETECTOR_STATUS_17_INFO);
            } else if (DETECTOR_STATUS_18.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(DETECTOR_STATUS_18_INFO);
            } else if (DETECTOR_STATUS_19.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(DETECTOR_STATUS_19_INFO);
            } else if (DETECTOR_STATUS_32.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(DETECTOR_STATUS_32_INFO);
            } else if (DETECTOR_STATUS_33.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(DETECTOR_STATUS_33_INFO);
            } else if (DETECTOR_STATUS_34.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(DETECTOR_STATUS_34_INFO);
            } else if (DETECTOR_STATUS_35.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(DETECTOR_STATUS_35_INFO);
            } else if (VALVE_BROKEN_STATUS_70.equals(controllerStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(VALVE_BROKEN_STATUS_70_INFO);
            }
        }

        //detectorStatus
        if (detectorStatus != null) {
            String info = "";
            // 当"控制器状态"存在,且非正常时,拼接状态
            if (!DETECTOR_STATUS_0.equals(controllerStatus) && controllerStatus != null) {
                info = preDeviceState.getDeviceStatusInfo() + ";";
            }
            if (DETECTOR_STATUS_0.equals(detectorStatus)) {
                // 一体设备 且上报了控制器状态
                if (controllerStatus != null) {
//                    if (DETECTOR_STATUS_0.equals(controllerStatus)) {
//                        preDeviceState.setDeviceStatus(DEVICE_STATUS_1);
//                        preDeviceState.setDeviceStatusInfo(info + DEVICE_STATUS_1_INFO);
//                    } else {
//                        //当控制器故障,设备整体状态故障
//                        preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
//                        preDeviceState.setDeviceStatusInfo(info + DEVICE_STATUS_1_INFO);
//                    }
                    // 分体探测器状态
                } else {
                    //分体 探测器可以决定状态,
                    preDeviceState.setDeviceStatus(DEVICE_STATUS_1);
                    preDeviceState.setDeviceStatusInfo(info + DEVICE_STATUS_1_INFO);
                }
            } else if (DETECTOR_STATUS_32.equals(detectorStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(info + DETECTOR_STATUS_32_INFO);
            } else if (DETECTOR_STATUS_33.equals(detectorStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(info + DETECTOR_STATUS_33_INFO);
            } else if (DETECTOR_STATUS_34.equals(detectorStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(info + DETECTOR_STATUS_34_INFO);
            } else if (DETECTOR_STATUS_35.equals(detectorStatus)) {
                preDeviceState.setDeviceStatus(DEVICE_STATUS_4);
                preDeviceState.setDeviceStatusInfo(info + DETECTOR_STATUS_35_INFO);
            }
        }
        //是否故障 0-否 1-是
        if (DEVICE_STATUS_4.equals(preDeviceState.getDeviceStatus())) {
            preDeviceState.setIsBroken(true);
            preDeviceState.setBrokenStatusInfo(preDeviceState.getDeviceStatusInfo());
        } else if (DEVICE_STATUS_1.equals(preDeviceState.getDeviceStatus())) {
            preDeviceState.setIsBroken(false);
            preDeviceState.setBrokenStatusInfo("");
        }
        log.info("setStatusInfo end preDeviceState:" + preDeviceState.toString());
    }

    /**
     * 校验紫荆wifi电磁阀某些故障忽略
     * @param valveStatusDesc
     * @param receiverValve
     * @return
     */
    private boolean checkZjWifiBrokenIsIgnore(String valveStatusDesc, ReceiverValve receiverValve){
        log.info("zjWifiValveCodeIgnore:{}",zjWifiValveCodeIgnore);
        if (StringUtils.isEmpty(zjWifiValveCodeIgnore) ||
                null==receiverValve ||
                StringUtils.isEmpty(receiverValve.getReceiverCode())){
            return false;
        }
        List<String> valveCodes = Arrays.asList(zjWifiValveCodeIgnore.split(","));
        return valveCodes.contains(receiverValve.getReceiverCode());
    }

    /**
     * 调用微信推送服务
     *
     * @param requests
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    protected void wechatNotify(List<BrowserNotifyItemRequest> requests) {

        try {
            String body = HttpRequest.post(gasWechatUrl + "/api/Notify/Receive")
                    .body(JSONObject.toJSONString(requests))
                    .execute()
                    .body();
            log.info("微信消息推送结果:{}", body);
        } catch (Exception e) {
            log.error("微信推送失败", e);
        }
    }

    /**
     * 调用微信推送服务(设备首次故障)
     *
     * @param requests
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    protected void wechatFirstBrokenNotify(List<BrowserNotifyItemRequest> requests) {

        try {
            String body = HttpRequest.post(gasWechatUrl + "/api/Notify/firstBroken")
                    .body(JSONObject.toJSONString(requests))
                    .execute()
                    .body();
            log.info("微信消息推送（设备首次故障）结果:{}", body);
        } catch (Exception e) {
            log.error("微信推送（设备首次故障）失败", e);
        }
    }

    /**
     * 调用本地推送服务
     *
     * @param requests
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    protected void consoleNotify(List<BrowserNotifyItemRequest> requests) {

        try {
            String body = HttpRequest.post(consoleUrl + "/api/inner/v1/browser/notify")
                    .body(JSONObject.toJSONString(requests))
                    .execute()
                    .body();
            log.info("本地消息推送结果:{}", body);
        } catch (Exception e) {
            log.error("本地消息推送失败", e);
        }
    }


    //发送短信
    protected void smsNotify(List<BrowserNotifyItemRequest> notifyRequest, Dtu dtu) {
        log.info("smsNotify-设备故障首次提醒（短信）:{},{}",
                JSONObject.toJSONString(notifyRequest), JSONObject.toJSONString(dtu));

        try {
            if (companyService == null || businessNoticeMapper == null || provider == null) {
                companyService = ApplicationContextUtils.getBean(CompanyServiceImpl.class);
                businessNoticeMapper = ApplicationContextUtils.getBean(BusinessNoticeMapper.class);
                provider = ApplicationContextUtils.getBean(VccAuthoritiesProvider.class);
                contactsMapper = ApplicationContextUtils.getBean(ContactsMapper.class);
//            redisTemplate = ApplicationContextUtils.getBean(RedisTemplate.class);
                sendMessageService = ApplicationContextUtils.getBean(SendMessageService.class);
                noticeMapper = ApplicationContextUtils.getBean(BusinessNoticeMapper.class);
                warnStrategyMapper = ApplicationContextUtils.getBean(WarnStrategyMapper.class);
                dtuMapper = ApplicationContextUtils.getBean(DtuMapper.class);
            }

            for (BrowserNotifyItemRequest request : notifyRequest) {
                QueryWrapper<BusinessNotice> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().or().eq(BusinessNotice::getSpId, dtu.getSpId())
                        .eq(BusinessNotice::getParamCode, "broken_first_time_msg")
                        .eq(BusinessNotice::getIsDeleted, 0)
                        .eq(BusinessNotice::getParamValue, "ON");
                List<BusinessNotice> businessNotices = businessNoticeMapper.selectList(queryWrapper);
                log.info("smsNotify-businessNotices:{}", JSONObject.toJSONString(businessNotices));
                if (CollectionUtils.isEmpty(businessNotices)) continue;
                BusinessNotice businessNotice = businessNotices.get(0);
                Integer level = StringUtils.isBlank(businessNotice.getPushLevel()) ? null : Integer.parseInt(businessNotice.getPushLevel());
                String pushStaffs = businessNotice.getPushStaffs();
                String pushPhones = businessNotice.getPushPhones();
                List<Map<String, Object>> list = contactsMapper.selectInfo(dtu.getConsumerId() + "");
                QueryWrapper<BusinessNotice> query = new QueryWrapper<>();
                query.lambda().or().eq(BusinessNotice::getIsDeleted, 0)
                        .eq(BusinessNotice::getSpId, dtu.getSpId())
                        .eq(BusinessNotice::getParamCode, CM_SERVICE_HOT_LINE);
                List<BusinessNotice> r = noticeMapper.selectList(query);
                log.info("smsNotify-r:{}", JSONObject.toJSONString(r));
                String phone = "";
                if (r == null) return;
                if (!CollectionUtil.isEmpty(r)) {
                    phone = r.get(0).getParamValue();
                }
                Consumer consumer = warnStrategyMapper.selectConsumerAndIndustry(request.getDtuId());
                String custAddress = consumer.getCustAddress();
                log.info("smsNotify-consumer:{}", JSONObject.toJSONString(consumer));
                if (consumer.getBindingOrderId() != null) {
                    custAddress = StringUtils.isEmpty(consumer.getAddress()) ? consumer.getRealAddress() : consumer.getAddress();
                }
                Map<String, Object> map = new HashMap<>();
                map.put("Time", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                map.put("position", consumer.getPosition());
                map.put("Equipmenttype", EquipmentTypeConst.equipmentTypeMaps.get(request.getEquipmentType()));
                map.put("subsName", StringUtils.isEmpty(consumer.getCustName()) ? " " : consumer.getCustName());
                map.put("address", custAddress);
                map.put("IMEI", request.getDtuId());
                map.put("Equipment_status", "故障");
                map.put("phone", phone);
                String factoryName = equipmentService.getEquipmentManufacturerName(dtu.getEquipmentManufacturer(), dtu.getSpId());
                map.put("factoryName", factoryName);
                sendSms(list, level, pushPhones, pushStaffs, map, dtu.getSpId(), dtu.getIMEI(), consumer.getId() + "");
            }
        } catch (Exception e) {
            log.info("smsNotify-error:{}", e);
        }
    }

    private void sendSms(List<Map<String, Object>> list, Integer pushLevel, String sendPhones,
                         String pushStaffs,
                         Map<String, Object> param,
                         String spId, String iMEI, String con) {
        log.info("sendSms-param:{},{}", JSONObject.toJSONString(list), JSONObject.toJSONString(param));
        //1发送企业员工
        try {
            if (!org.springframework.util.StringUtils.isEmpty(pushStaffs)) {
                //走企业联系人
                String[] split = pushStaffs.split(AbstractCmpDataNotifyService.split);
                for (String s : split) {
                    //获取对应手机号
                    log.info("send-Sms-员工:{}", JSONObject.toJSONString(s));
                    if (pushSMS(param, s, spId, iMEI, con, 0, 1))
                        continue;
                }
            }
            //2.发送客户联系人
            if (pushLevel != null || pushLevel != 0) {
                if (!CollectionUtil.isEmpty(list)) {
                    List<Integer> objs = new ArrayList<>();
                    list.forEach(stringObjectMap -> {
                        objs.add(Integer.parseInt(stringObjectMap.get("level") + ""));
                    });
                    if (!objs.contains(pushLevel)) {
                        List<Map<String, Object>> listCopy = new ArrayList<>();
                        for (Map<String, Object> map : list) {
                            if (pushLevel > Integer.parseInt(map.get("level") + "")) {
                                listCopy.add(map);
                            }
                        }
                        if (CollectionUtil.isEmpty(listCopy)) {
                            log.info("sendSms-pushLevel，此级别没有合适的下级发送人：{}，客户id:{}"
                                    , pushLevel, con);
                        } else {
                            listCopy.sort((o1, o2) -> {
                                return -Integer.parseInt(o1.get("level") + "")
                                        + Integer.parseInt(o2.get("level") + "");
                            });
                            pushLevel = Integer.parseInt(listCopy.get(0).get("level") + "");
                        }
                    }
                    for (Map<String, Object> map : list) {
                        log.info("sendSms-level:{}", Integer.parseInt(map.get("level") + ""));
                        log.info("sendSms-pushLevel:{}", pushLevel);
                        if (Integer.parseInt(map.get("level") + "")
                                == pushLevel || pushLevel.equals(map.get("level"))) {
                            String telephone = map.get("telephone") + "";
                            if (!StringUtils.isEmpty(telephone)) {
                                pushSMS(param, telephone, spId, iMEI,
                                        con, pushLevel, 0);
                                continue;
                            } else {
                                pushLevel = pushLevel + 1;
                            }
                        }
                    }
                }
            }
            //额外手机号：
            log.info("send-sendPhones:{}", JSONObject.toJSONString(sendPhones));
            if (!StringUtils.isEmpty(sendPhones)) {
                String[] split = sendPhones.split(AbstractCmpDataNotifyService.split);
                for (String s : split) {
                    log.info("send-s:{}", JSONObject.toJSONString(s));
                    pushSMS(param, s, spId, iMEI, con, 0, 3);
                }
            }
        } catch (Exception e) {
            log.error("sendSms-error:{}", e);
        }
    }

    private boolean pushSMS(Map<String, Object> param,
                            String telephone, String spId, String iMEI,
                            String con, Integer level, int type) {
        try {
            log.info("detailOpt-本次发送短信内容:{}:{}msgType:{}", telephone, param);
            if (StringUtils.isEmpty(telephone)) {
                log.info("pushSMS-手机号不能为空:{}", spId, iMEI, con,
                        level, telephone);
                return false;
            }
            //调用外部短信接口
            String orgCode = companyService.getOrgCode(spId,con);
            Map<String, Object> sms = sendMessageService
                    .sendSms(sendMessageService
                                    .getRequestParam(telephone
                                            , Constants.WARN_Alarm_equipment_fault_no1, orgCode
                                            , param, "sms", null, null, null, 0)
                            , "");

            Object errorMsg = "";
            if (sms.get("data") != null) {
                log.info("detailOpt—短信发送人；{}", telephone);
                HashMap<String, Object> req = new HashMap<>();
                req.put("ids", sms.get("data"));
                req.put("orgCode", orgCode);
                try {
                    //延迟获取回执
                    Map<String, Object> map = sendMessageService.subTaskDetail(req, "");
                    if (map != null) errorMsg = map.get("errorMsg");
                } catch (Exception e) {
                    log.info("subTaskDetail-error:{}", e);
                }
                log.info("sendSms-发送remark:{}", errorMsg);
            } else {
                errorMsg = sms.get("errMsg");
            }
            log.info(spId, iMEI, con,
                    level, errorMsg, sms.get("data") + "", telephone, type);
            log.info("sendSms-发送日志:{}回执消息:{}", telephone, JSONObject.toJSONString(sms));
        } catch (Exception e) {
            log.error("pushSMS-error:{}", e);
        }
        return true;
    }

}
